package com.devices;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Properties;

import org.apache.log4j.Logger;

import matlabcontrol.MatlabConnectionException;
import matlabcontrol.MatlabInvocationException;
import matlabcontrol.MatlabProxy;
import matlabcontrol.MatlabProxyFactory;
import matlabcontrol.extensions.MatlabNumericArray;
import matlabcontrol.extensions.MatlabTypeConverter;

public class MatlabConnection implements Predictable{
	private MatlabProxyFactory factory;
	private MatlabProxy proxy;
	private String configFile="config.txt";
	
	
	private String scriptsFolder;
	private String fileFolder;
	private String networkName="net";
	private String isNetTaught="isNetTaught";
	private String teachNeuralFunctionName;
	private String predictNeuralFunctionName;
	private String fileWithoutoExtension;
	private final static Logger LOGGER = Logger.getLogger(MatlabConnection.class
			.getName());
	
	public MatlabConnection() throws IOException{
		try {
			loadProperties(configFile);
		} catch (FileNotFoundException e) {
			LOGGER.error("Couldont open property file: " + configFile, e);
			throw e;
		} catch (IOException e) {
			LOGGER.error("Couldn't load properties", e);
			throw e;
		}
		LOGGER.info(fileFolder+scriptsFolder+teachNeuralFunctionName+predictNeuralFunctionName);
	};
	
	private void loadProperties(String fileName) throws FileNotFoundException,IOException {
		LOGGER.trace("method: loadProperties("+fileName+")");
		FileReader fr1 = new FileReader(fileName);
		BufferedReader br1 = new BufferedReader(fr1);
		Properties prop1 = new Properties();
		prop1.load(br1);
		fileFolder=prop1.getProperty("historicalFileFolder");
		scriptsFolder=prop1.getProperty("scriptsFolder");
		teachNeuralFunctionName=prop1.getProperty("teachNeuralFunctionName");
		predictNeuralFunctionName=prop1.getProperty("predictNeuralFunctionName");		
	}
	
	public void start() throws MatlabConnectionException{
		LOGGER.trace("method: start()"); 
		factory= new MatlabProxyFactory();
		proxy= factory.getProxy();
	}
	
	public void end(){
		LOGGER.trace("method: end()");
		proxy.disconnect();
	}
	@Override
	public void teachNeuralNetwork(String filename) throws MatlabInvocationException{
		LOGGER.trace("method: teachNeuralNetwork("+filename+")");
		fileWithoutoExtension=filename.substring(0, filename.indexOf("."));
		proxy.eval("cd ('"+scriptsFolder+"');");
		proxy.eval("load "+fileFolder+filename+";");
		proxy.eval(isNetTaught+"=false;");
		proxy.eval(networkName+"="+teachNeuralFunctionName+"("+fileWithoutoExtension+");");
		proxy.eval(isNetTaught+"=true;");
		
	}
	@Override
	public boolean isNeuralNetworkTaught() throws MatlabInvocationException{
		LOGGER.trace("method: isNeuralNetworkTaught()");
		boolean isNetTaught = ((boolean[]) proxy.getVariable("isNetTaught"))[0];
		if(isNetTaught==true)
			return true;
		else
			return false;
	}

	@Override
	public HashMap<Calendar, Double> predict(Calendar[] dates) throws MatlabInvocationException {
		LOGGER.trace("method: predict("+dates+")");
		double[][] array =  new double[dates.length][1];
		for(int i=0;i<dates.length;i++){
			String doubleS=String.valueOf(dates[i].get(Calendar.YEAR))+String.valueOf(dates[i].get(Calendar.MONTH))
					+String.valueOf(dates[i].get(Calendar.DAY_OF_WEEK));
			array[i][0]=Double.valueOf(doubleS);
		}
		MatlabTypeConverter processor = new MatlabTypeConverter(proxy);
		processor.setNumericArray("dates", new MatlabNumericArray(array, null));
		proxy.eval("result="+predictNeuralFunctionName+"(dates,"+networkName+","+fileWithoutoExtension+")");
		double[][] result= processor.getNumericArray("result").getRealArray2D();
		HashMap<Calendar, Double> predictedValues =  new HashMap<Calendar, Double>();
		for(int i=0;i<dates.length;i++){
			predictedValues.put(dates[i], Double.valueOf(result[i][1]));
		}
		fileWithoutoExtension=null;
		return predictedValues;
	}
	

}
